﻿using System.Runtime.CompilerServices;
using AutoWiring.Model;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json.Linq;

namespace AutoWiring.Common
{
    public static class comMethod
    {
        // 定义XYZ类
        public class XYZNew
        {
            public double X { get; set; }
            public double Y { get; set; }
            public double Z { get; set; }
        }

        public static string GetMD5Hash(string input)
        {
            // 创建一个MD5对象
            using MD5 md5 = MD5.Create();
            // 将输入字符串转换为字节数组并计算其散列数据
            byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(input));

            // 创建一个新的Stringbuilder来收集字节并创建一个字符串
            StringBuilder sBuilder = new StringBuilder();

            // 循环遍历每个字节的散列数据 
            // 并格式化为十六进制字符串
            foreach (var t in data)
            {
                sBuilder.Append(t.ToString("x2"));
            }

            // 返回十六进制字符串
            return sBuilder.ToString();
        }

        /// <summary>
        /// 机柜前的支架宽度（也同时看成支架宽度）
        /// </summary>
        /// <param name="ccisList"></param>
        /// <returns></returns>
        public static double GetWidth(List<CableContactItemSave> ccisList)
        {
            double width = 0;
            // 存储已经处理过的支架，以避免重复
            HashSet<string> processedSupports = new HashSet<string>();

            foreach (var ccis in ccisList)
            {
                // 解析 ZJxyzList
                List<XYZ> zjxyzList = JsonConvert.DeserializeObject<List<XYZ>>(ccis.ZJxyzList);

                // 获取后两个 ZJxyz 坐标点，判断是否为同一个支架
                XYZ lastPoint1 = zjxyzList[^2]; // 倒数第二个点
                XYZ lastPoint2 = zjxyzList[^1]; // 最后一个点
                // 构造唯一的支架标识符
                string supportIdentifier =
                    $"{lastPoint1.X},{lastPoint1.Y},{lastPoint1.Z}-{lastPoint2.X},{lastPoint2.Y},{lastPoint2.Z}";

                // 检查是否已经处理过这个支架
                if (!processedSupports.Add(supportIdentifier))
                {
                    // 如果已处理，跳过
                    Console.WriteLine($"支架 {supportIdentifier} 已存在，跳过");
                    continue;
                }

                // 如果是新支架，进行处理并添加到已处理集合
                // 计算支架的宽度：取前两个点的 X 坐标差
                XYZ firstPoint1 = zjxyzList[0];
                XYZ firstPoint2 = zjxyzList[1];
                // 支架宽度
                width = Math.Abs(firstPoint1.X - firstPoint2.X);
            }

            return Math.Round(width, 4);
        }

        /// <summary>
        /// 获取支架对应的CableContactItemSave
        /// </summary>
        /// <param name="ccisList"></param>
        /// <param name="xyzEndList">终点集合列表</param>
        /// <param name="xyzStartList">起点集合列表</param>
        /// <returns></returns>
        public static CableContactItemSave GetZhiJia(List<CableContactItemSave> ccisList, List<XYZ> xyzEndList,
            List<XYZ> xyzStartList, CableContactItemExe ccie)
        {
            ccie.ZJxyzDict = new Dictionary<string, List<XYZ>>();
            // 使用 HashSet 来避免重复的 ZJxyzList (根据最后两个点过滤)
            HashSet<string> processedSupports = new HashSet<string>();


            // 初始化变量用于保存最终的支架
            CableContactItemSave bestCcis = null;
            double minDistance = double.MaxValue;

            foreach (var ccis in ccisList)
            {
                // 解析 ZJxyzList
                List<XYZ> zjxyzList = JsonConvert.DeserializeObject<List<XYZ>>(ccis.ZJxyzList);

                // 过滤少于两个点的 ZJxyzList
                if (zjxyzList.Count < 2)
                {
                    Console.WriteLine("ZJxyzList 少于两个点，无法计算支架");
                    continue;
                }

                // 获取 ZJxyzList 的最后两个点
                XYZ firstSupport = zjxyzList[^2]; // 倒数第二个点
                XYZ lastSupport = zjxyzList[^1]; // 最后一个点

                // 使用最后两个点生成唯一标识符用于过滤重复项
                string supportIdentifier =
                    $"{firstSupport.X},{firstSupport.Y},{firstSupport.Z}-{lastSupport.X},{lastSupport.Y},{lastSupport.Z}";


                // 如果该支架组已经处理过，跳过
                if (processedSupports.Add(supportIdentifier))
                {
                    ccie.ZJxyzDict.Add(supportIdentifier, zjxyzList);
                }
                else
                {
                    Console.WriteLine("重复的支架组，跳过...");
                    continue;
                }


                // 添加到已处理集合中

                // 计算该支架组的中心点（基于最后两个点）
                XYZ zjCenter = new XYZ(
                    (firstSupport.X + lastSupport.X) / 2,
                    (firstSupport.Y + lastSupport.Y) / 2,
                    (firstSupport.Z + lastSupport.Z) / 2
                );

// 机柜中心点
                XYZ jgCenter = CalculateCenterPoint(xyzEndList);

// 变压器中心点
                XYZ byqCenter = CalculateCenterPoint(xyzStartList);

                // 计算 ZJxyzList 支架组的中心点与 JGConnItemList 中心点的距离
                double distance = CalculateDistance(zjCenter, jgCenter);

                // 判断 ZJxyzList 的中心点的 Y 值是否在 JGConnItemList 中心点和 BYQConnItemList 中心点的 Y 值范围内
                if (zjCenter.Y >= Math.Min(jgCenter.Y, byqCenter.Y) && zjCenter.Y <= Math.Max(jgCenter.Y, byqCenter.Y))
                {
                    // 比较最小距离
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        bestCcis = ccis; // 更新为当前最接近的支架组
                    }
                }

                ZhiJiaModel ZJ = new ZhiJiaModel();
                ZJ.Name = supportIdentifier;
                ZJ.BYQ = ccis.cableNumber;
                ZJ.Location = firstSupport;
                    
                Global.ZJModelList.Add(ZJ);
            }

            return bestCcis;
        }

        /// <summary>
        /// 计算点集合的中心点
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public static XYZ CalculateCenterPoint(List<XYZ> points)
        {
            //保留4位小数
            double centerX = Math.Round(points.Average(p => p.X), 4);
            double centerY = Math.Round(points.Average(p => p.Y), 4);
            double centerZ = Math.Round(points.Average(p => p.Z), 4);

            return new XYZ(centerX, centerY, centerZ);
        }


        /// <summary>
        /// 计算两点之间的距离
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        /// <returns></returns>
        public static double CalculateDistance(XYZ point1, XYZ point2)
        {
            return Math.Round(Math.Sqrt(
                Math.Pow(point1.X - point2.X, 2) +
                Math.Pow(point1.Y - point2.Y, 2) +
                Math.Pow(point1.Z - point2.Z, 2)
            ), 4);
        }

        /// <summary>
        /// 线缆沟末端中心点
        /// </summary>
        /// <param name="firstSupport"></param>
        /// <param name="secondSupport"></param>
        /// <returns></returns>
        public static XYZ CenterPoint(XYZ firstSupport, XYZ secondSupport)
        {
            double centerX = (firstSupport.X + secondSupport.X) / 2;
            double centerY = (firstSupport.Y + secondSupport.Y) / 2;
            double centerZ = (firstSupport.Z + secondSupport.Z) / 2;

            return new XYZ(centerX, centerY, centerZ);
        }

        /// <summary>
        /// 主道路宽度
        /// </summary>
        /// <param name="jsonString"></param>
        public static double MainWidth(string jsonString)
        {
            // 反序列化为 List<XYZ>
            List<XYZ> mainWidthPoints = JsonConvert.DeserializeObject<List<XYZ>>(jsonString);

            // 计算Y值差，即主干道宽度
            double mainWidth = Math.Abs(mainWidthPoints[0].Y - mainWidthPoints[1].Y);

            return mainWidth;
        }

        public static double JXMainWidth(string jsonString)
        {
            // 反序列化为 List<XYZ>
            List<XYZ> mainWidthPoints = JsonConvert.DeserializeObject<List<XYZ>>(jsonString);

            // 计算Y值差，即主干道宽度
            double mainWidth = Math.Abs(mainWidthPoints[0].Y - mainWidthPoints[1].Y);

            return mainWidth;
        }

        /// <summary>
        /// 找出主干道两个点中与变压器中心点距离最近的点
        /// </summary>
        /// <param name="byqCenter">变压器中心点</param>
        /// <param name="jsonString">传入的json字符串</param>
        /// <returns>距离最近的点</returns>
        public static List<XYZ> GetNearestPoints(XYZ byqCenter, string jsonString)
        {
            // 反序列化为 List<XYZ>
            List<XYZ> mainWidthPoints = JsonConvert.DeserializeObject<List<XYZ>>(jsonString);

            // 计算两个点到 byqCenter 的距离
            double distance1 = CalculateDistance(byqCenter, mainWidthPoints[0]);
            double distance2 = CalculateDistance(byqCenter, mainWidthPoints[1]);

            // 按照距离排序并返回集合 距离近在第一个，距离远的在第二个
            return distance1 < distance2
                ? [mainWidthPoints[0], mainWidthPoints[1]]
                : [mainWidthPoints[1], mainWidthPoints[0]];
        }

        /// <summary>
        /// 变压器的点解析，以字典的形式存储每个编码和对应的XYZ坐标，并且给xyzStartList赋值
        /// </summary>
        /// <param name="ccisList"></param>
        /// <param name="ccie"></param>
        public static void BYQItemList(List<CableContactItemSave> ccisList, CableContactItemExe ccie)
        {
            // 找到与 ccie.cableStart 对应的 BYQConnItemList
            var byqConnItemListJson = ccisList.Find(e => e.cableStart == ccie.cableStart)?.BYQConnItemList;
            var byqConnItemCenterListJson = ccisList.Find(e => e.cableNumber == ccie.cableNumber)?.BYQConnItemList;

            //找到当前请求数据线的编码
            string LineCode = ccie.cableStart[^1].ToString();

            // 反序列化 BYQConnItemList 为 List<BYQConnItem>
            // 电缆起点连接件的中心
            List<BYQConnItem> byqConnItems;
            // 电缆起点中心
            List<BYQConnItem> byqConnItemsCenter;

            try
            {
                byqConnItems = JsonConvert.DeserializeObject<List<BYQConnItem>>(byqConnItemListJson);
                byqConnItemsCenter = JsonConvert.DeserializeObject<List<BYQConnItem>>(byqConnItemCenterListJson);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"反序列化失败：{ex.Message}");
                return;
            }

            // 如果反序列化结果为空，直接返回
            if (byqConnItems == null || byqConnItems.Count == 0)
            {
                Console.WriteLine("反序列化后的列表为空。");
                return;
            }

            // 确保字典已初始化
            ccie.xyzStartDic ??= new Dictionary<string, XYZ>();

            // 遍历每个组，并添加到字典
            foreach (var item in byqConnItems)
            {
                // 添加到字典，TFCode 作为 key，XYZ 作为 value
                if (!ccie.xyzStartDic.ContainsKey(item.TFCode))
                {
                    if (item.TFCode.Contains(LineCode))
                    {
                        ccie.xyzStartDic.Add(item.TFCode, item.XYZ);
                    }
                }
            }

            ccie.xyzStartDic = ccie.xyzStartDic
                .OrderByDescending(entry =>
                {
                    // 提取 key 的最后一部分，转换为整数
                    string key = entry.Key;
                    string lastPart = key.Split('-').Last(); // 提取 '-' 后的部分
                    return int.TryParse(lastPart, out int num) ? num : int.MaxValue; // 按数字排序，无法转换为数字的放最后
                })
                .ToDictionary(entry => entry.Key, entry => entry.Value);

            List<XYZ> byqCenterList = new List<XYZ>();
            foreach (var item in byqConnItemsCenter)
            {
                byqCenterList.Add(item.XYZ);
            }

            // 计算所有 X, Y, Z 坐标的平均值
            double centerX = byqCenterList.Average(point => point.X);
            double centerY = byqCenterList.Average(point => point.Y);
            double centerZ = byqCenterList.Average(point => point.Z);

            ccie.startPointCenter = new XYZ(centerX, centerY, centerZ);
            //xyzStartList赋值 为后续计算使用
            ccie.xyzStartList = ccie.xyzStartDic.Values.ToList();
        }

        /// <summary>
        /// 机柜的点解析，以字典的形式存储每个编码和对应的XYZ坐标，并且给xyzEndDic赋值
        /// </summary>
        /// <param name="ccisList"></param>
        /// <param name="ccie"></param>
        public static void JGItemList(List<CableContactItemSave> ccisList, CableContactItemExe ccie)
        {
            // 找到与 ccie.cableStart 对应的 BYQConnItemList
            var jgConnItemListJson = ccisList.Find(e => e.cableEnd == ccie.cableEnd)?.JGConnItemList;
            var jgConnItemCenterListJson = ccisList.Find(e => e.cableNumber == ccie.cableNumber)?.JGConnItemList;

            // 反序列化 JGConnItemList 为 List<JGConnItem>
            List<JGConnItem> jgConnItems;
            List<JGConnItem> jgConnItemsCenter;

            try
            {
                jgConnItems = JsonConvert.DeserializeObject<List<JGConnItem>>(jgConnItemListJson);
                jgConnItemsCenter = JsonConvert.DeserializeObject<List<JGConnItem>>(jgConnItemCenterListJson);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"反序列化失败：{ex.Message}");
                return;
            }

            // 如果反序列化结果为空，直接返回
            if (jgConnItems == null || jgConnItems.Count == 0)
            {
                Console.WriteLine("反序列化后的列表为空。");
                return;
            }

            // 确保字典已初始化
            if (ccie.xyzEndDic == null || ccie.xyzEndLineList == null)
            {
                ccie.xyzEndDic = new Dictionary<string, XYZ>();
                ccie.xyzEndLineList = new List<XYZ>();
            }

            //找到当前请求数据线的编码
            string LineCode = ccie.cableStart[^1].ToString();

            List<XYZ> jgCenterList = new List<XYZ>();
            // 遍历每个组，并添加到字典
            foreach (var item in jgConnItems)
            {
                // 添加到字典，TFCode 作为 key，XYZ 作为 value
                if (!ccie.xyzEndDic.ContainsKey(item.TFCode))
                {
                    if (item.TFCode.Contains(LineCode))
                    {
                        ccie.xyzEndLineList.Add(item.XYZ);
                    }

                    jgCenterList.Add(item.XYZ);
                    ccie.xyzEndDic.Add(item.TFCode, item.XYZ);
                }
            }

            // 计算所有 X, Y, Z 坐标的平均值
            double centerX = jgCenterList.Average(point => point.X);
            double centerY = jgCenterList.Average(point => point.Y);
            double centerZ = jgCenterList.Average(point => point.Z);

            ccie.endPointCenter = new XYZ(centerX, centerY, centerZ);

            //xyzStartList赋值 为后续计算使用
            ccie.xyzEndList = ccie.xyzEndDic.Values.ToList();
        }

        /// <summary>
        /// 根据偏移距离对多段线进行偏移，并返回左偏移点集合、右偏移点集合以及中间的集合
        /// </summary>
        /// <param name="ccie">该数据的所有信息</param>
        /// <param name="points">要平移的集合点</param>
        /// <param name="offsetDistance">水平方向平移的距离(半径的3倍)</param>
        /// <param name="VertialSpace">支架每层间隔</param>
        /// <param name="supportIntervalLevelHeight">线缆沟外支架层高</param>
        /// <param name="supportFirstLevelHeight">线缆沟外支架底层层高</param>
        /// <param name="isOneTwo">是否走12层</param>
        public static (List<XYZ> leftOffsetPoints, List<XYZ> rightOffsetPoints, List<XYZ> pointsNew) OffsetPolyline(
            CableContactItemExe ccie,
            List<XYZ> points, double offsetDistance, double VertialSpace, double supportIntervalLevelHeight,
            double supportFirstLevelHeight, bool isOneTwo)
        {
            List<XYZ> leftOffsetPoints = new List<XYZ>(); //左平移
            List<XYZ> rightOffsetPoints = new List<XYZ>(); //右平移


            for (int i = 0; i < points.Count - 2; i++)
            {
                XYZ point = points[i];
                XYZ pointCenter = points[i + 1];
                XYZ pointFinal = points[i + 2];
                // 计算两个方向向量
                XYZ v1 = pointCenter.Subtract(point).Normalize();
                XYZ v2 = pointFinal.Subtract(pointCenter).Normalize();
                // 计算角平分线方向 
                XYZ sumV = v1.Add(v2).Normalize();

                XYZ leftOffsetV = XYZ.RotateByAngleAroundZ(sumV, -Math.PI / 2).Multiply(offsetDistance); // 逆时针旋转 90 度
                XYZ rightOffsetV = XYZ.RotateByAngleAroundZ(sumV, Math.PI / 2).Multiply(offsetDistance); // 顺时针旋转 90 度


                if (i == 0)
                {
                    XYZ firstOffsetV = v1.CrossProduct(XYZ.BaseZ).Normalize().Multiply(offsetDistance);

                    #region 平移第一个点

                    leftOffsetPoints.Add(point.Add(firstOffsetV)); //左平移
                    rightOffsetPoints.Add(point.Add(firstOffsetV.Negate())); //右平移

                    #endregion
                }

                #region 平移中间点

                leftOffsetPoints.Add(pointCenter.Add(leftOffsetV));
                rightOffsetPoints.Add(pointCenter.Add(rightOffsetV));

                #endregion

                if (i == points.Count - 3)
                {
                    XYZ firstOffsetV = v2.CrossProduct(XYZ.BaseZ).Normalize().Multiply(offsetDistance);

                    #region 平移最后一个点

                    leftOffsetPoints.Add(pointFinal.Add(firstOffsetV));
                    rightOffsetPoints.Add(pointFinal.Add(firstOffsetV.Negate()));

                    #endregion
                }
            }

            leftOffsetPoints.RemoveAll(point =>
                double.IsNaN(point.X) || double.IsNaN(point.Y) || double.IsNaN(point.Z));
            rightOffsetPoints.RemoveAll(point =>
                double.IsNaN(point.X) || double.IsNaN(point.Y) || double.IsNaN(point.Z));

            //改变线缆沟外支架的点(改的只是第一层)
            points[^2] = new XYZ(points[^2].X, points[^2].Y,
                supportFirstLevelHeight);
            leftOffsetPoints[^2] = new XYZ(leftOffsetPoints[^2].X,
                leftOffsetPoints[^2].Y, supportFirstLevelHeight);
            rightOffsetPoints[^2] = new XYZ(rightOffsetPoints[^2].X,
                rightOffsetPoints[^2].Y, supportFirstLevelHeight);

            if (ccie.isTop)
            {
                if (isOneTwo)
                {
                    //如果是都1层，则不变
                    //中间
                    // 遍历 points 并修改 Z 值
                    for (int i = 0; i < points.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = points[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        points[i] = new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace);
                    }

                    //如果不是走12层，则走34层，平移后的点,z值要加两倍的层高
                    //右侧
                    // 遍历 rightOffsetPoints 并修改 Z 值
                    for (int i = 0; i < rightOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = rightOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        rightOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace);
                    }

                    //左侧
                    // 遍历 leftOffsetPoints 并修改 Z 值
                    for (int i = 0; i < leftOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = leftOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        leftOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace);
                    }

                    points[^2] = new XYZ(points[^2].X, points[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    leftOffsetPoints[^2] = new XYZ(
                        leftOffsetPoints[^2].X,
                        leftOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    rightOffsetPoints[^2] = new XYZ(
                        rightOffsetPoints[^2].X,
                        rightOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);
                }
                else
                {
                    //中间
                    // 遍历 points 并修改 Z 值
                    for (int i = 0; i < points.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = points[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        points[i] = new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 3 * VertialSpace);
                    }

                    //如果不是走12层，则走34层，平移后的点,z值要加两倍的层高
                    //右侧
                    // 遍历 rightOffsetPoints 并修改 Z 值
                    for (int i = 0; i < rightOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = rightOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        rightOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 3 * VertialSpace);
                    }

                    //左侧
                    // 遍历 leftOffsetPoints 并修改 Z 值
                    for (int i = 0; i < leftOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = leftOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        leftOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 3 * VertialSpace);
                    }

                    points[^2] = new XYZ(points[^2].X, points[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    leftOffsetPoints[^2] = new XYZ(
                        leftOffsetPoints[^2].X,
                        leftOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    rightOffsetPoints[^2] = new XYZ(
                        rightOffsetPoints[^2].X,
                        rightOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);
                }
            }
            else
            {
                if (isOneTwo)
                {
                    //如果是都12层，则不变
                }
                else
                {
                    //中间
                    // 遍历 points 并修改 Z 值
                    for (int i = 0; i < points.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = points[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        points[i] = new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 1 * VertialSpace);
                    }

                    //如果不是走12层，则走34层，平移后的点,z值要加两倍的层高
                    //右侧
                    // 遍历 rightOffsetPoints 并修改 Z 值
                    for (int i = 0; i < rightOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = rightOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        rightOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 1 * VertialSpace);
                    }

                    //左侧
                    // 遍历 leftOffsetPoints 并修改 Z 值
                    for (int i = 0; i < leftOffsetPoints.Count; i++)
                    {
                        // 获取当前点
                        XYZ currentPoint = leftOffsetPoints[i];

                        // 修改 Z 值为 Z + 2 * VertialSpace
                        leftOffsetPoints[i] =
                            new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 1 * VertialSpace);
                    }

                    points[^2] = new XYZ(points[^2].X, points[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    leftOffsetPoints[^2] = new XYZ(
                        leftOffsetPoints[^2].X,
                        leftOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);

                    rightOffsetPoints[^2] = new XYZ(
                        rightOffsetPoints[^2].X,
                        rightOffsetPoints[^2].Y,
                        supportFirstLevelHeight + 2 * supportIntervalLevelHeight);
                }
            }


            //List<XYZ> pointsNew = new List<XYZ>();
            //pointsNew = points;
            return (leftOffsetPoints, rightOffsetPoints, points);
        }

        /// <summary>
        /// 馈线侧的上下分层
        /// </summary>
        /// <param name="ccie"></param>
        public static (List<XYZ> points, List<XYZ> upOnePoints, List<XYZ> upTwoPoints) PolylineUpDown(
            CableContactItemExe ccie)
        {
            //初始化
            List<XYZ> newList = new List<XYZ>();
            foreach (var VARIABLE in ccie.resultPointList)
            {
                newList.Add(VARIABLE);
            }

            List<XYZ> points = newList;
            double VertialSpace = ccie.InHeight;
            double supportFirstLevelHeight = ccie.supportFirstLevelHeight;
            double supportIntervalLevelHeight = ccie.supportIntervalLevelHeight;

            //
            List<XYZ> upOnePoints = new List<XYZ>(); //上一层
            List<XYZ> upTwoPoints = new List<XYZ>(); //上两层


            //中间
            // 遍历 points 并修改 Z 值
            for (int i = 0; i < points.Count; i++)
            {
                // 获取当前点
                XYZ currentPoint = points[i];

                // 修改 Z 值为 Z + 2 * VertialSpace
                // points[i] = new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace);
                upOnePoints.Add(new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 1 * VertialSpace));
                upTwoPoints.Add(new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace));
            }


            points[^2] = new XYZ(points[^2].X, points[^2].Y,
                supportFirstLevelHeight);

            upOnePoints[^2] = new XYZ(upOnePoints[^2].X, upOnePoints[^2].Y,
                supportFirstLevelHeight + 1 * supportIntervalLevelHeight);

            upTwoPoints[^2] = new XYZ(upTwoPoints[^2].X, upTwoPoints[^2].Y,
                supportFirstLevelHeight + 2 * supportIntervalLevelHeight);


            return (points, upOnePoints, upTwoPoints);
        }

        /// <summary>
        /// 馈线侧的上下分层
        /// </summary>
        /// <param name="ccie"></param>
        public static (List<XYZ> downPoints, List<XYZ> points, List<XYZ> upPoints ) NewPolylineUpDown(
            CableContactItemExe ccie)
        {
            //初始化
            List<XYZ> points = ccie.resultPointList;
            double VertialSpace = ccie.InHeight;
            double supportFirstLevelHeight = ccie.supportFirstLevelHeight;
            double supportIntervalLevelHeight = ccie.supportIntervalLevelHeight;

            //
            List<XYZ> upPoints = new List<XYZ>(); //上一层
            List<XYZ> downPoints = new List<XYZ>(); //下两层


            //中间
            // 遍历 points 并修改 Z 值
            for (int i = 0; i < points.Count; i++)
            {
                // 获取当前点
                XYZ currentPoint = points[i];

                // 修改 Z 值为 Z + 2 * VertialSpace
                // points[i] = new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 2 * VertialSpace);
                upPoints.Add(new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z + 1 * VertialSpace));
                downPoints.Add(new XYZ(currentPoint.X, currentPoint.Y, currentPoint.Z - 1 * VertialSpace));
            }


            points[^2] = new XYZ(points[^2].X, points[^2].Y,
                supportFirstLevelHeight);

            upPoints[^2] = new XYZ(upPoints[^2].X, upPoints[^2].Y,
                supportFirstLevelHeight + 1 * supportIntervalLevelHeight);

            downPoints[^2] = new XYZ(downPoints[^2].X, downPoints[^2].Y,
                supportFirstLevelHeight - 1 * supportIntervalLevelHeight);


            return (downPoints, points, upPoints);
        }

        /// <summary>
        /// 找到起点连接件和终点连接件相互对应连接的点
        /// </summary>
        /// <param name="xyzStartDic">起点连接件字典</param>
        /// <param name="xyzEndDic">终点连接件字典</param>
        public static Dictionary<string, List<XYZ>> StartEndSamePoint(Dictionary<string, XYZ> xyzStartDic,
            Dictionary<string, XYZ> xyzEndDic)
        {
            // 创建一个新的字典，key 为相同的 key，value 为 List<XYZ>
            Dictionary<string, List<XYZ>> resultDic = new Dictionary<string, List<XYZ>>();

            // 遍历 xyzStartDic，检查相同的 key
            foreach (var kvp in xyzStartDic)
            {
                string key = kvp.Key;

                // 检查 xyzEndDic 是否包含相同的 key
                if (xyzEndDic.TryGetValue(key, out var value))
                {
                    // 创建一个新的 List<XYZ>，先添加 xyzStartDic 的值，再添加 xyzEndDic 的值
                    List<XYZ> xyzList =
                    [
                        kvp.Value, // 先存储 xyzStartDic 中的 value
                        value
                    ];

                    // 将结果存入 resultDic
                    //key为起点的key线的编码，value为起点和终点的坐标
                    resultDic.Add(key, xyzList);
                }
            }

            return resultDic;
        }

        /// <summary>
        /// 预留槽的Z值修改
        /// </summary>
        /// <param name="ccie"></param>
        public static void YCLZValue(CableContactItemExe ccie)
        {
            double newZValue = ccie.InLevelHeight;
            // 遍历集合，将每个点的 Z 值修改为 ccie.InHeight 的值
            for (int i = 0; i < ccie.reservedSlotList.Count; i++)
            {
                XYZ point = ccie.reservedSlotList[i];

                // 创建一个新的 XYZ 对象，替换 Z 值为 newZValue
                ccie.reservedSlotList[i] = new XYZ(point.X, point.Y, newZValue);
            }
        }

        /// <summary>
        /// 处理设备的起点和终点
        /// </summary>
        /// <param name="ccie"></param>
        /// <param name="startEndPoint"></param>
        public static void ProcessSortedLine(CableContactItemExe ccie, Dictionary<string, List<XYZ>> startEndPoint)
        {
            //重新排序
            ccie.resultPointDic.OrderBy(entry =>
                {
                    string key = entry.Key;
                    string lastPart = key.Split('-').Last();
                    return int.TryParse(lastPart, out int num) ? num : int.MaxValue; // 按数字排序，无法转换为数字的放最后
                })
                .ToDictionary(entry => entry.Key, entry => entry.Value);


            //初始化
            var resultPointList = ccie.resultPointDic.ToList();
            double InLevelHeight = ccie.InLevelHeight;
            int index = 0;

            int count = 0;
            foreach (var item in ccie.xyzStartDic)
            {
                // 确保 resultPointList 中存在足够的数据来处理
                if (index >= resultPointList.Count)
                    break; // 防止索引超出范围

                // 1. 取出 resultPointDic 的当前条信息
                var currentEntry = resultPointList[index]; // 取出第 index 条信息
                //当前信息的线编码key
                string originalKey = currentEntry.Key;
                //当前信息的线集合点
                List<XYZ> pointList = currentEntry.Value;

                string newKey = item.Key; // 获取当前 sortedKeys 的 key
                if (ccie.isJinXian)
                {
                    // 2. 去掉 List 集合中的第一个点和最后一个点
                    if (pointList.Count > 2) // 只有当列表有至少 3 个点时才执行
                    {
                        pointList.RemoveAt(0); // 去掉第一个点
                        pointList.RemoveAt(pointList.Count - 1); // 去掉最后一个点
                    }

                    // 3. 将原 key 改为 sortedKeys 的当前 key
                    List<XYZ> valueList;
                    //将sortedKeys的value第一个值放到pointList第一个位置，第二个值放到最后一个位置
                    startEndPoint.TryGetValue(newKey, out valueList); //如果找到了该编码的坐标点，列表第一个为起点，第二个为终点

                    //集合点的改变

                    //处理起点的数据
                    //将起点放到第一个位置中，将终点放到最后一个位置中
                    pointList.Insert(0, valueList[0]); //第一个点
                    pointList.Add(valueList[1]);
                    //计算起点连接件下方的一个点
                    XYZ newXYZ = new XYZ(valueList[0].X, valueList[0].Y, InLevelHeight);
                    //起点下方的点，应插入到起点后的位置
                    pointList.Insert(1, newXYZ); //起点下方的点

                    count++;
                }
                else
                {
                    //馈线侧
                    // 2. 去掉 List 集合中的第一个点和最后一个点
                    if (pointList.Count > 2) // 只有当列表有至少 3 个点时才执行
                    {
                        pointList.RemoveAt(0); // 去掉第一个点
                        pointList.RemoveAt(pointList.Count - 1); // 去掉最后一个点
                    }

                    // 3. 将原 key 改为 sortedKeys 的当前 key
                    List<XYZ> valueList;
                    //将sortedKeys的value第一个值放到pointList第一个位置，第二个值放到最后一个位置
                    startEndPoint.TryGetValue(newKey, out valueList); //如果找到了该编码的坐标点，列表第一个为起点，第二个为终点
                    //集合点的改变
                    //处理起点的数据
                    //将起点放到第一个位置中，将终点放到最后一个位置中
                    pointList.Insert(0, valueList[0]); //第一个点
                    pointList.Add(valueList[1]);
                    //计算起点连接件下方的一个点
                    XYZ newXYZ = new XYZ(valueList[0].X, valueList[0].Y, InLevelHeight);
                    //起点下方的点，应插入到起点后的位置
                    pointList.Insert(1, newXYZ); //第二个点
                    count++;
                }

                // 4. 从 resultPointDic 中移除原有的当前条信息并加入新的 key 和处理后的 List
                ccie.resultPointDic.Remove(originalKey); // 移除原来的 key
                ccie.resultPointDic.Add(newKey, pointList); // 使用新的 key 加入字典
                // 增加索引，用于在下一次循环时取下一条数据
                index++;
            }
        }

        /// <summary>
        /// 处理终点
        /// </summary>
        public static void EndProcessing(CableContactItemExe ccie)
        {
            int index = 0;


            XYZ firstPoint = ccie.firstSupport;
            //比较机柜终点的前后顺序并排序
            ccie.resultPointDic = ccie.resultPointDic
                .OrderByDescending(kvp => CalculateDistance(firstPoint, kvp.Value[^1]))
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            // //每段线进行偏移
            foreach (var kvp in ccie.resultPointDic.Keys)
            {
                double x = ccie.xyzEndLineList.Average(point => point.X);
                double y = ccie.xyzEndLineList.Average(point => point.Y);
                double z = ccie.xyzEndLineList.Average(point => point.Z);
                XYZ pointCenter = new XYZ(x, y, z);

                //点在机柜右侧  在支架右侧  加
                if (ccie.resultPointDic[kvp][^2].X > ccie.ZhiJiaList[2].X && pointCenter.X > ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.secondSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.supportFirstLevelHeight + ccie.supportIntervalLevelHeight * index);
                    
                    //从第二个交点开始由横向变竖向
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.secondSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.InLevelHeight + ccie.InHeight * index);
                }

                //点在机柜左侧 在支架右侧
                if (ccie.resultPointDic[kvp][^2].X > ccie.ZhiJiaList[2].X && pointCenter.X < ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.secondSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.supportFirstLevelHeight + ccie.supportIntervalLevelHeight * index);
                    
                    //从第二个交点开始由横向变竖向
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.secondSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.InLevelHeight + ccie.InHeight * index);
                }

                //点在机柜右侧 在支架左侧
                if (ccie.resultPointDic[kvp][^2].X < ccie.ZhiJiaList[2].X && pointCenter.X > ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.firstSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.supportFirstLevelHeight + ccie.supportIntervalLevelHeight * index);
                    
                    //从第二个交点开始由横向变竖向
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.firstSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.InLevelHeight + ccie.InHeight * index);
                }

                //在支架左侧 在机柜左侧
                if (ccie.resultPointDic[kvp][^2].X < ccie.ZhiJiaList[2].X && pointCenter.X < ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.firstSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.supportFirstLevelHeight + ccie.supportIntervalLevelHeight * index);
                    
                    //从第二个交点开始由横向变竖向
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.firstSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.InLevelHeight + ccie.InHeight * index);
                }

                XYZ pointZhiJia = null;
                if (!ccie.isSameZhiJia)
                {
                    pointZhiJia = new XYZ(ccie.resultPointDic[kvp][^3].X, ccie.ZhiJiaList[3].Y,
                        ccie.resultPointDic[kvp][^2].Z);
                    ccie.resultPointDic[kvp].RemoveAt(ccie.resultPointDic[kvp].Count - 3);
                    ccie.resultPointDic[kvp].Insert(ccie.resultPointDic[kvp].Count - 2, pointZhiJia);
                }

                XYZ pointNew = new XYZ(ccie.resultPointDic[kvp][^1].X, ccie.resultPointDic[kvp][^1].Y,
                    ccie.resultPointDic[kvp][^2].Z);

                ccie.resultPointDic[kvp].Insert(ccie.resultPointDic[kvp].Count - 1, pointNew);
                index++;
            }
        }

        /// <summary>
        /// 馈线侧终点连接机柜的点处理
        /// </summary>
        /// <param name="ccie"></param>
        public static void VerticalEndProcessing(CableContactItemExe ccie)
        {
            XYZ firstPoint = ccie.firstSupport;
            //比较机柜终点的前后顺序并排序
            ccie.resultPointDic = ccie.resultPointDic
                .OrderByDescending(kvp => CalculateDistance(firstPoint, kvp.Value[^1]))
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);


            // //每段线进行偏移
            foreach (var kvp in ccie.resultPointDic.Keys)
            {
                //线的中心点
                double x = ccie.xyzEndLineList.Average(point => point.X);
                double y = ccie.xyzEndLineList.Average(point => point.Y);
                double z = ccie.xyzEndLineList.Average(point => point.Z);
                XYZ pointCenter = new XYZ(x, y, z);


                // 在支架右侧  线在机柜右侧
                if (!ccie.isLeft && pointCenter.X > ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.firstSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.resultPointDic[kvp][^2].Z);
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.firstSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.resultPointDic[kvp][^3].Z);
                    ccie.resultPointDic[kvp][^4] = new XYZ(ccie.firstSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^4].Y,
                        ccie.resultPointDic[kvp][^4].Z);
                    ccie.resultPointDic[kvp][^5] = new XYZ(ccie.firstSupport.X - ccie.moveValue,
                        ccie.resultPointDic[kvp][^6].Y,
                        ccie.resultPointDic[kvp][^6].Z);
                }

                //在支架右侧 线在机柜左侧 
                if (!ccie.isLeft && pointCenter.X < ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.firstSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.resultPointDic[kvp][^2].Z);
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.firstSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.resultPointDic[kvp][^3].Z);
                    ccie.resultPointDic[kvp][^4] = new XYZ(ccie.firstSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^4].Y,
                        ccie.resultPointDic[kvp][^4].Z);
                    ccie.resultPointDic[kvp][^5] = new XYZ(ccie.firstSupport.X - ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^6].Y,
                        ccie.resultPointDic[kvp][^6].Z);
                }

                //在支架左侧 线在机柜右侧 
                if (ccie.isLeft && pointCenter.X > ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.secondSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.resultPointDic[kvp][^2].Z);
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.secondSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.resultPointDic[kvp][^3].Z);
                    ccie.resultPointDic[kvp][^4] = new XYZ(ccie.secondSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^4].Y,
                        ccie.resultPointDic[kvp][^4].Z);
                    ccie.resultPointDic[kvp][^5] = new XYZ(ccie.secondSupport.X + ccie.moveValue * 2,
                        ccie.resultPointDic[kvp][^6].Y,
                        ccie.resultPointDic[kvp][^6].Z);
                }

                //在支架左侧 线在机柜左侧
                if (ccie.isLeft && pointCenter.X < ccie.endPointCenter.X)
                {
                    ccie.resultPointDic[kvp][^2] = new XYZ(ccie.secondSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^2].Y,
                        ccie.resultPointDic[kvp][^2].Z);
                    ccie.resultPointDic[kvp][^3] = new XYZ(ccie.secondSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^3].Y,
                        ccie.resultPointDic[kvp][^3].Z);
                    ccie.resultPointDic[kvp][^4] = new XYZ(ccie.secondSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^4].Y,
                        ccie.resultPointDic[kvp][^4].Z);
                    ccie.resultPointDic[kvp][^5] = new XYZ(ccie.secondSupport.X + ccie.moveValue,
                        ccie.resultPointDic[kvp][^6].Y,
                        ccie.resultPointDic[kvp][^6].Z);
                }

                //增加机柜竖直向下的点
                XYZ endAddPoint = new XYZ(ccie.resultPointDic[kvp][^2].X, ccie.resultPointDic[kvp][^1].Y,
                    ccie.resultPointDic[kvp][^2].Z);
                ccie.resultPointDic[kvp].Insert(ccie.resultPointDic[kvp].Count - 1, endAddPoint);
            }
        }


        /// <summary>
        /// 预留槽的y值增加一个值
        /// </summary>
        /// <param name="slotList"></param>
        /// <param name="yValue"></param>
        /// <param name="yAxis"></param>
        public static void UpdateYValues(List<XYZ> slotList, double yValue, int yAxis)
        {
            if (yAxis > 0)
            {
                foreach (var item in slotList)
                {
                    item.Y -= yValue;
                }
            }
            else
            {
                foreach (var item in slotList)
                {
                    item.Y += yValue;
                }
            }
        }

        /// 二阶贝塞尔曲线公式：三个控制点 p0, p1, p2，返回3D坐标点
        public static XYZ QuadraticBezier3D(XYZ p0, XYZ p1, XYZ p2, double t)
        {
            double x = Math.Pow(1 - t, 2) * p0.X +
                       2 * (1 - t) * t * p1.X +
                       Math.Pow(t, 2) * p2.X;

            double y = Math.Pow(1 - t, 2) * p0.Y +
                       2 * (1 - t) * t * p1.Y +
                       Math.Pow(t, 2) * p2.Y;

            double z = Math.Pow(1 - t, 2) * p0.Z +
                       2 * (1 - t) * t * p1.Z +
                       Math.Pow(t, 2) * p2.Z;

            return new XYZ(x, y, z);
        }

        #region 二次曲线

        public static List<XYZ> generalArc(XYZ p0, XYZ p1, XYZ p2)
        {
            List<XYZ> results = new List<XYZ>();
            for (double t = 0; t < 1; t += 0.1)
            {
                results.Add(getPointByParam(t, p0, p1, p2));
            }

            return results;
        }

        private static XYZ getPointByParam(double t, XYZ p0, XYZ p1, XYZ p2)
        {
            XYZ p0Result = p0.Multiply(Math.Pow(1 - t, 2));
            XYZ p1Result = p1.Multiply(2 * t * (1 - t));
            XYZ p2Result = p2.Multiply(Math.Pow(t, 2));
            XYZ result = p0Result.Add(p1Result).Add(p2Result);
            return result;
        }

        #endregion

        #region 三次曲线

        /// <summary>
        /// 三次曲线
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <returns></returns>
        public static List<XYZ> GeneralCubicCurve(XYZ p0, XYZ p1, XYZ p2, XYZ p3)
        {
            List<XYZ> results = new List<XYZ>();
            for (double t = 0; t <= 1; t += 0.1)
            {
                results.Add(GetCubicPointByParam(t, p0, p1, p2, p3));
            }

            return results;
        }

        private static XYZ GetCubicPointByParam(double t, XYZ p0, XYZ p1, XYZ p2, XYZ p3)
        {
            XYZ p0Result = p0.Multiply(Math.Pow(1 - t, 3));
            XYZ p1Result = p1.Multiply(3 * t * Math.Pow(1 - t, 2));
            XYZ p2Result = p2.Multiply(3 * Math.Pow(t, 2) * (1 - t));
            XYZ p3Result = p3.Multiply(Math.Pow(t, 3));
            XYZ result = p0Result.Add(p1Result).Add(p2Result).Add(p3Result);
            return result;
        }

        #endregion

        #region 四次曲线

        /// <summary>
        /// 四次曲线
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="p4"></param>
        /// <returns></returns>
        public static List<XYZ> GeneralQuarticCurve(XYZ p0, XYZ p1, XYZ p2, XYZ p3, XYZ p4)
        {
            List<XYZ> results = new List<XYZ>();
            for (double t = 0; t <= 1; t += 0.1)
            {
                results.Add(GetQuarticPointByParam(t, p0, p1, p2, p3, p4));
            }

            return results;
        }

        private static XYZ GetQuarticPointByParam(double t, XYZ p0, XYZ p1, XYZ p2, XYZ p3, XYZ p4)
        {
            XYZ p0Result = p0.Multiply(Math.Pow(1 - t, 4));
            XYZ p1Result = p1.Multiply(4 * t * Math.Pow(1 - t, 3));
            XYZ p2Result = p2.Multiply(6 * Math.Pow(t, 2) * Math.Pow(1 - t, 2));
            XYZ p3Result = p3.Multiply(4 * Math.Pow(t, 3) * (1 - t));
            XYZ p4Result = p4.Multiply(Math.Pow(t, 4));
            XYZ result = p0Result.Add(p1Result).Add(p2Result).Add(p3Result).Add(p4Result);
            return result;
        }

        #endregion

        /// <summary>
        /// 通过计算每三个连续点之间的夹角来判断是否有拐点。如果夹角小于某个值，就可以认为存在拐点，然后使用曲线方法来生成平滑的过渡
        /// </summary>
        /// <param name="resultPointList"></param>
        /// <param name="arcRadius"></param>
        public static void SmoothCorners(List<XYZ> resultPointList, double arcRadius, double JXmainWidth)
        {
            // 创建一个新的点列表来存储平滑后的路径
            List<XYZ> smoothedPointList = new List<XYZ>();

            // 确保有足够的点来检测拐点
            if (resultPointList.Count < 4)
            {
                return;
            }

            // 添加第一个点
            //smoothedPointList.Add(resultPointList[0]);

            for (int i = 1; i < resultPointList.Count - 1; i++)
            {
                if (i < 2)
                {
                    XYZ previousPoint = new XYZ(resultPointList[i - 1].X, resultPointList[i - 1].Y, -500);
                    ;
                    XYZ currentPoint = resultPointList[i];
                    XYZ nextPoint = resultPointList[i + 1];

                    XYZ vector1 = previousPoint.Subtract(currentPoint).Normalize();
                    XYZ vector2 = nextPoint.Subtract(currentPoint).Normalize();

                    XYZ arcStartPoint = currentPoint.Add(vector1.Multiply(arcRadius));
                    XYZ arcEndPoint = currentPoint.Add(vector2.Multiply(arcRadius));

                    List<XYZ> arcPoints = comMethod.generalArc(previousPoint, currentPoint, nextPoint);
                    smoothedPointList.AddRange(arcPoints);
                }
                else if (i > resultPointList.Count - 3)
                {
                    // 集合末尾的值
                    XYZ previousPoint = resultPointList[i - 1];
                    XYZ currentPoint = resultPointList[i];
                    XYZ nextPoint = resultPointList[i + 1];
                    List<XYZ> arcPoints = comMethod.generalArc(previousPoint, currentPoint, nextPoint);
                    smoothedPointList.AddRange(arcPoints);
                }
                else if (i == resultPointList.Count - 3)
                {
                    continue;
                }
                else
                {
                    XYZ previousPoint = resultPointList[i - 1];
                    XYZ currentPoint = resultPointList[i];
                    XYZ nextPoint = resultPointList[i + 1];


                    // 计算前后两个向量


                    XYZ vector1 = previousPoint.Subtract(currentPoint).Normalize();
                    XYZ vector2 = nextPoint.Subtract(currentPoint).Normalize();

                    // 计算向量之间的夹角
                    double angle = vector1.AngleTo(vector2);
                    // 设定一个误差范围
                    // 设定新的误差范围
                    double lowerThreshold = 85 * Math.PI / 180; // 40度转为弧度
                    double upperThreshold = 95 * Math.PI / 180; // 140度转为弧度

                    // 如果角度小于阈值，认为是拐点
                    if (angle >= lowerThreshold && angle <= upperThreshold)
                    {
                        // 计算拐点的两个方向的端点
                        XYZ arcStartPoint = currentPoint.Add(vector1.Multiply(arcRadius));
                        XYZ arcEndPoint = currentPoint.Add(vector2.Multiply(arcRadius));

                        // 生成平滑过渡的曲线段，并添加到 smoothedPointList 中
                        List<XYZ> arcPoints = comMethod.generalArc(arcStartPoint, currentPoint, arcEndPoint);
                        smoothedPointList.AddRange(arcPoints);
                    }
                    else
                    {
                        // 如果没有拐点，直接添加当前点
                        smoothedPointList.Add(currentPoint);
                    }
                }
            }

            // 添加最后一个点
            smoothedPointList.Add(resultPointList[resultPointList.Count - 1]);

            // 将平滑后的点列表替换原始列表
            resultPointList.Clear();
            resultPointList.AddRange(smoothedPointList);
        }


        /// <summary>
        /// 馈线侧预留区域，起点在支架点的左侧,跳对面
        /// </summary>
        /// <param name="firstPoint1"></param>
        /// <param name="ccie"></param>
        /// <returns></returns>
        public static List<XYZ> KXLineAdjustedYLPoint(XYZ firstPoint1, CableContactItemExe ccie)
        {
            List<XYZ> resultPointList = new List<XYZ>();

            double mainWidth = ccie.KXmainWidth;

            double cableRadius = ccie.cableRadius;
            // 新点的初始位置为 firstPoint1 的坐标
            double newX = ccie.startPointCenter.X;
            if (LineAndCenterPoint(ccie))
            {
                // 左侧
                newX += mainWidth + mainWidth / 8;
            }
            else
            {
                // 右侧
                newX += mainWidth;
            }

            XYZ firstYLPoint = new XYZ(newX, firstPoint1.Y, firstPoint1.Z);

            // 跳回来
            XYZ secondYLPoint = new XYZ(firstYLPoint.X,
                firstYLPoint.Y - mainWidth + cableRadius * 2 * 8, firstYLPoint.Z);
            //沿X走一截
            XYZ thirdYLPoint = null;
            if (LineAndCenterPoint(ccie))
            {
                thirdYLPoint = new XYZ(secondYLPoint.X + mainWidth, secondYLPoint.Y,
                    secondYLPoint.Z);
            }
            else
            {
                thirdYLPoint = new XYZ(secondYLPoint.X + mainWidth + mainWidth / 4, secondYLPoint.Y,
                    secondYLPoint.Z);
            }

            //跳回去
            XYZ forthYLPoint = new XYZ(thirdYLPoint.X, thirdYLPoint.Y + mainWidth - cableRadius * 2 * 8,
                thirdYLPoint.Z);

            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            resultPointList.Add(thirdYLPoint);
            resultPointList.Add(forthYLPoint);

            return resultPointList;
        }

        /// <summary>
        /// 馈线侧预留区域，起点在支架点的右侧,跳对面
        /// </summary>
        /// <param name="firstPoint1"></param>
        /// <param name="ccie"></param>
        /// <returns></returns>
        public static List<XYZ> KXRightLineAdjustedYLPoint(XYZ firstPoint1, CableContactItemExe ccie)
        {
            List<XYZ> resultPointList = new List<XYZ>();

            double mainWidth = ccie.KXmainWidth;

            double cableRadius = ccie.cableRadius;
            // 新点的初始位置为 firstPoint1 的坐标
            double newX = ccie.startPointCenter.X;
            if (LineAndCenterPoint(ccie))
            {
                // 左侧
                newX =newX- mainWidth;
            }
            else
            {
                // 右侧
                newX =newX- mainWidth -mainWidth / 8;
            }

            XYZ firstYLPoint = new XYZ(newX, firstPoint1.Y, firstPoint1.Z); 

            // 跳回来
            XYZ secondYLPoint = new XYZ(firstYLPoint.X,
                firstYLPoint.Y - mainWidth + cableRadius * 2 * 8, firstYLPoint.Z);
            //沿X走一截
            XYZ thirdYLPoint = null;
            if (LineAndCenterPoint(ccie))
            {
                thirdYLPoint = new XYZ(secondYLPoint.X - mainWidth, secondYLPoint.Y,
                    secondYLPoint.Z);
            }
            else
            {
                thirdYLPoint = new XYZ(secondYLPoint.X - mainWidth + mainWidth / 4, secondYLPoint.Y,
                    secondYLPoint.Z);
            }

            //跳回去
            XYZ forthYLPoint = new XYZ(thirdYLPoint.X, thirdYLPoint.Y + mainWidth - cableRadius * 2 * 8,
                thirdYLPoint.Z);

            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            resultPointList.Add(thirdYLPoint);
            resultPointList.Add(forthYLPoint);

            return resultPointList;
        }

        /// <summary>
        /// 馈线侧预留区域，起点在支架点的左侧,不跳对面
        /// </summary>
        /// <param name="firstPoint"></param>
        /// <param name="ccie"></param>
        /// <param name="ZJCenterPoint"></param>
        /// <returns></returns>
        public static List<XYZ> KXLineYLPoint(XYZ firstPoint, CableContactItemExe ccie, XYZ ZJCenterPoint)
        {
            // 最终返回的结果集
            List<XYZ> resultPointList = new List<XYZ>();

            // 馈线侧宽度
            double WidthValue = ccie.KXmainWidth;

            // 半径
            double cableRadius = ccie.cableRadius;
            // 支架组的相关信息
            Dictionary<string, List<XYZ>> ZJxyzDict = ccie.ZJxyzDict;

            // 找到各个支架的X值，并添加到集合中
            List<double> ZJXList = new List<double>();
            foreach (KeyValuePair<string, List<XYZ>> kvp in ZJxyzDict)
            {
                double ZJXValue = kvp.Value.First().X;
                ZJXList.Add(ZJXValue);
            }


            // 计算 X 值的距离
            double distanceX = ZJXList.Average();

            // 根据距离来判断新的 X 值的增减
            if (LineAndCenterPoint(ccie))
            {
                // 左侧
                distanceX -= WidthValue / 4;
            }
            else
            {
                // 右侧
                distanceX -= WidthValue / 8;
            }


            //预留区域第一个点
            XYZ firstYLPoint = new XYZ(distanceX, firstPoint.Y, firstPoint.Z);
            //跳对面
            XYZ secondYLPoint = null;
            if (LineAndCenterPoint(ccie))
            {
                secondYLPoint = new XYZ(firstYLPoint.X, firstYLPoint.Y + WidthValue - cableRadius * 4 * 6,
                    firstYLPoint.Z);
            }
            else
            {
                secondYLPoint = new XYZ(firstYLPoint.X, firstYLPoint.Y + WidthValue - cableRadius * 4*2,
                    firstYLPoint.Z);
            }

            //往回沿X走一截
            XYZ thirdPoint = null;
            double XValue = Math.Abs(ZJCenterPoint.X - ccie.ZhiJiaList[2].X) / 2;
            if (distanceX > WidthValue)
            {
                //thirdPoint = new XYZ(secondYLPoint.X + WidthValue / 2 * 3, secondYLPoint.Y, secondYLPoint.Z);
            }
            else
            {
                thirdPoint = new XYZ(secondYLPoint.X - XValue, secondYLPoint.Y, secondYLPoint.Z);
            }

            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            if (thirdPoint != null)
            {
                resultPointList.Add(thirdPoint);
            }

            // 返回新的点，Y 和 Z 坐标保持与 PointCenter 相同
            return resultPointList;
        }

          /// <summary>
        /// 馈线侧预留区域，起点在支架点的右侧,不跳对面
        /// </summary>
        /// <param name="firstPoint"></param>
        /// <param name="ccie"></param>
        /// <param name="ZJCenterPoint"></param>
        /// <returns></returns>
        public static List<XYZ> KXLineRightYLPoint(XYZ firstPoint, CableContactItemExe ccie, XYZ ZJCenterPoint)
        {
            // 最终返回的结果集
            List<XYZ> resultPointList = new List<XYZ>();

            // 馈线侧宽度
            double WidthValue = ccie.KXmainWidth;

            // 半径
            double cableRadius = ccie.cableRadius;
            // 支架组的相关信息
            Dictionary<string, List<XYZ>> ZJxyzDict = ccie.ZJxyzDict;

            // 找到各个支架的X值，并添加到集合中
            List<double> ZJXList = new List<double>();
            foreach (KeyValuePair<string, List<XYZ>> kvp in ZJxyzDict)
            {
                double ZJXValue = kvp.Value.First().X;
                ZJXList.Add(ZJXValue);
            }


            // 计算 X 值的距离
            double distanceX = ZJXList.Average();

            // 根据距离来判断新的 X 值的增减
            if (LineAndCenterPoint(ccie))
            {
                // 左侧
                distanceX =distanceX+ WidthValue / 8;
            }
            else
            {
                // 右侧
                distanceX =distanceX+ WidthValue / 4;
            }


            //预留区域第一个点
            XYZ firstYLPoint = new XYZ(distanceX, firstPoint.Y, firstPoint.Z);
            //跳对面
            XYZ secondYLPoint = null;
            if (LineAndCenterPoint(ccie))
            {
                secondYLPoint = new XYZ(firstYLPoint.X, firstYLPoint.Y + WidthValue - cableRadius * 4*2 ,
                    firstYLPoint.Z);
            }
            else
            {
                secondYLPoint = new XYZ(firstYLPoint.X, firstYLPoint.Y + WidthValue - cableRadius * 4* 6,
                    firstYLPoint.Z);
            }

            //往回沿X走一截
            XYZ thirdPoint = null;
            double XValue = Math.Abs(ZJCenterPoint.X - ccie.ZhiJiaList[2].X) / 2;
            if (distanceX > WidthValue)
            {
                //thirdPoint = new XYZ(secondYLPoint.X + WidthValue / 2 * 3, secondYLPoint.Y, secondYLPoint.Z);
            }
            else
            {
                thirdPoint = new XYZ(secondYLPoint.X + XValue, secondYLPoint.Y, secondYLPoint.Z);
            }

            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            if (thirdPoint != null)
            {
                resultPointList.Add(thirdPoint);
            }

            // 返回新的点，Y 和 Z 坐标保持与 PointCenter 相同
            return resultPointList;
        }
        /// <summary>
        /// 馈线侧预留区域跳到对面
        /// </summary>
        /// <param name="firstPoint1"></param>
        /// <param name="secondPoint1"></param>
        /// <param name="mainWidth"></param>
        /// <param name="startPointCenter"></param>
        /// <param name="cableRadius"></param>
        /// <returns></returns>
        public static List<XYZ> GetAdjustedPoint(XYZ firstPoint1, XYZ secondPoint1, double mainWidth,
            XYZ startPointCenter, double cableRadius)
        {
            List<XYZ> resultPointList = new List<XYZ>();

            // 新点的初始位置为 firstPoint1 的坐标
            double newX = startPointCenter.X;

            // 判断 secondPoint1 是否在 firstPoint1 的左侧或右侧
            if (secondPoint1.X > startPointCenter.X)
            {
                // 右侧，X 值右移 100
                newX += mainWidth;
            }
            else
            {
                // 左侧，X 值左移 100
                newX -= mainWidth;
            }

            XYZ firstYLPoint = new XYZ(newX, firstPoint1.Y, firstPoint1.Z);
            //跳回来
            XYZ secondYLPoint = new XYZ(firstYLPoint.X,
                firstYLPoint.Y - mainWidth + cableRadius * 2 * 8, firstYLPoint.Z);
            //沿X走一截
            XYZ thirdYLPoint = null;
            if (secondPoint1.X > startPointCenter.X)
            {
                thirdYLPoint = new XYZ(secondYLPoint.X + mainWidth, secondYLPoint.Y,
                    secondYLPoint.Z);
            }
            else
            {
                thirdYLPoint = new XYZ(secondYLPoint.X - mainWidth, secondYLPoint.Y,
                    secondYLPoint.Z);
            }

            //跳回去
            XYZ forthYLPoint = new XYZ(thirdYLPoint.X, thirdYLPoint.Y + mainWidth - cableRadius * 2 * 8,
                thirdYLPoint.Z);
            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            resultPointList.Add(thirdYLPoint);
            resultPointList.Add(forthYLPoint);


            // 返回新创建的点，Y 和 Z 值保持不变
            return resultPointList;
        }

        /// <summary>
        /// 馈线侧预留区域不跳到对面
        /// </summary>
        /// <param name="PointCenter">设备起点中心点</param>
        /// <param name="ZhiJiaListPoint">要比较的支架点</param>
        /// <param name="WidthValue">宽度值</param>
        /// <param name="firstPoint">第一个交点坐标</param>
        /// <returns></returns>
        public static List<XYZ> GetAdjustedPointBasedOnWidth(XYZ PointCenter, XYZ ZhiJiaListPoint, double WidthValue,
            XYZ firstPoint, double cableRadius)
        {
            List<XYZ> resultPointList = new List<XYZ>();
            // 计算 X 值的距离
            double distanceX = Math.Abs(PointCenter.X - ZhiJiaListPoint.X);

            // 根据距离来判断新的 X 值的增减
            double newX = PointCenter.X;
            if (distanceX > WidthValue)
            {
                // 如果距离大于 WidthValue，新点的 X 值减 100
                newX -= WidthValue * 3;
            }
            else
            {
                // 如果距离小于等于 WidthValue，新点的 X 值加 100
                newX += WidthValue / 2 * 3;
            }


            //预留区域第一个点
            XYZ firstYLPoint = new XYZ(newX, firstPoint.Y, firstPoint.Z);
            //跳对面
            XYZ secondYLPoint = new XYZ(firstYLPoint.X, firstYLPoint.Y + WidthValue - cableRadius * 2 * 8,
                firstYLPoint.Z);

            //往回沿X走一截
            XYZ thirdPoint = null;
            if (distanceX > WidthValue)
            {
                //thirdPoint = new XYZ(secondYLPoint.X + WidthValue / 2 * 3, secondYLPoint.Y, secondYLPoint.Z);
            }
            else
            {
                thirdPoint = new XYZ(secondYLPoint.X - WidthValue / 2 * 3, secondYLPoint.Y, secondYLPoint.Z);
            }

            resultPointList.Add(firstYLPoint);
            resultPointList.Add(secondYLPoint);
            if (thirdPoint != null)
            {
                resultPointList.Add(thirdPoint);
            }

            // 返回新的点，Y 和 Z 坐标保持与 PointCenter 相同
            return resultPointList;
        }


        /// <summary>
        /// 各支架组的中心点
        /// </summary>
        /// <param name="ccie"></param>
        public static XYZ KXJGLoaction(CableContactItemExe ccie)
        {
            double y = 0.0000;
            double z = 0.0000;
            //每组支架的第一个点的x值集合
            List<double> ZJxValueList = new List<double>();
            foreach (var VARIABLE in ccie.ZJxyzDict)
            {
                ZJxValueList.Add(VARIABLE.Value[0].X);
                y = VARIABLE.Value[0].Y;
                z = VARIABLE.Value[0].Z;
            }

            double XValue = 0.0000;
            for (int i = 0; i < ZJxValueList.Count - 1; i++)
            {
                XValue += ZJxValueList[i];
            }

            XValue /= ZJxValueList.Count;

            // 最终得到的支架组中心点的坐标
            return new XYZ(XValue, y, z);
        }

        /// <summary>
        /// 起点是否在支架组支架的左侧
        /// </summary>
        /// <param name="ZJCenterPoint">支架组的坐标</param>
        /// <param name="startPointCenter">起点中心点的坐标</param>
        /// <returns>如果是false则起点在右侧，如果是ture则起点在左侧</returns>
        public static bool ZJAndStart(XYZ ZJCenterPoint, XYZ startPointCenter)
        {
            //起点在支架组支架的左侧还是右侧
            bool isLeft = false;
            if (startPointCenter.X > ZJCenterPoint.X)
            {
                isLeft = false;
            }
            else
            {
                isLeft = true;
            }

            return isLeft;
        }

        /// <summary>
        /// 起点连接件是否在起点设备中心点的左侧
        /// </summary>
        /// <param name="ccie"></param>
        /// <returns>true是在左侧，false在右侧</returns>
        public static bool LineAndCenterPoint(CableContactItemExe ccie)
        {
            bool isLeft = false;

            if (ccie.xyzStartList[0].X < ccie.startPointCenter.X)
            {
                isLeft = true;
            }
            else
            {
                isLeft = false;
            }

            return isLeft;
        }

        /// <summary>
        /// 解析传过来的json字符串，并赋值
        /// </summary>
        /// <param name="jsonStr"></param>
        /// <param name="mw"></param>
        public static void ParsingJsonString(string jsonString)
        {
            #region 解析最外层 JSON

            // 解析最外层 JSON  
            JObject jsonObject = JObject.Parse(jsonString);

            // 解析 CommonConfig 部分
            var commonConfig = jsonObject["CommonConfig"];

            //主干道宽度
            string mainWidth = commonConfig["MainWidth"]?.ToString();
            //进线侧主干道宽度
            string JXmainWidth = commonConfig["JXMainWidth"]?.ToString();
            //馈线侧主干道宽度
            string KXmainWidth = commonConfig["KXMainWidth"]?.ToString();
            //电缆直径
            string diameter = commonConfig["Diameter"]?.ToString();
            //支架底层高度
            string csBottomHeight = commonConfig["CSBottomHeight"]?.ToString();
            //支架层距
            string csLayerSpace = commonConfig["CSLayerSpace"]?.ToString();
            //机柜支架底层高度
            string jsBottomHeight = commonConfig["JSBottomHeight"]?.ToString();
            //机柜支架层距
            string jsLayerSpace = commonConfig["JSLayerSpace"]?.ToString();

            #endregion
        }
        
        
        /// <summary>
        /// 坐标点去重
        /// </summary>
        /// <param name="xyzs"></param>
        /// <returns></returns>
        public static List<XYZ> exDistinctElement(List<XYZ> xyzs)
        {
            List<XYZ> result = new List<XYZ>();
            foreach (XYZ xyz in xyzs)
            {
                bool isExist = false;
                foreach (XYZ z in result)
                {
                    if (z.DistanceTo(xyz)==0)
                    {
                        isExist = true;
                        break;
                    }
                }
                if (!isExist)
                {
                    result.Add(new XYZ(xyz.X, xyz.Y, xyz.Z));
                }
            }

            return result;
        }
    }
}